import "@site/src/languages/highlight";

# 编写场景创建模块

&emsp;&emsp;欢迎来到Dora SSR游戏引擎横版2D游戏开发教程的第三篇！在这篇教程中，我们将介绍如何创建游戏场景。这个模块主要做两件事：一是创建游戏场景的物理对象，二是添加场景的可视图形对象。这些对象都会被挂载到游戏场景树中。

&emsp;&emsp;首先，我们需要引入一些必要的模块：

```tl title="Script/Scene.tl"
local Platformer <const> = require("Platformer")
local Vec2 <const> = require("Vec2")
local Rect <const> = require("Rect")
local BodyDef <const> = require("BodyDef")
local Body <const> = require("Body")
local Director <const> = require("Director")
local App <const> = require("App")
local Color <const> = require("Color")
local View <const> = require("View")
local Entity <const> = require("Entity")
local Rectangle <const> = require("UI.View.Shape.Rectangle")
local Config <const> = require("Script.Config")
local Loader <const> = require("Script.Loader")
```

&emsp;&emsp;接着，我们定义了一些颜色和设计宽度的参数：

```tl title="Script/Scene.tl"
local themeColor = App.themeColor
local fillColor = Color(themeColor:toColor3(), 0x66):toARGB()
local borderColor = themeColor:toARGB()
local DesignWidth <const> = 1000
```

&emsp;&emsp;然后，我们创建了一个[PlatformWorld](/docs/api/Class/Platformer/PlatformWorld)对象，并设置了相机的边界、跟随比例和缩放比例。这里的[world.camera](/docs/api/Class/Platformer/PlatformWorld#camera)是一个[PlatformCamera](/docs/api/Class/Platformer/PlatformCamera)对象，它是用于2D平台游戏的相机，可以跟踪游戏单位的移动并保持其在相机视野内。[boundary](/docs/api/Class/Platformer/PlatformCamera#boundary)是相机可见范围的矩形区域，[followRatio](/docs/api/Class/Platformer/PlatformCamera#followratio)是相机移动以跟随目标位置的速率，[zoom](/docs/api/Class/Platformer/PlatformCamera#zoom)是相机的缩放系数，1.0表示正常大小，2.0表示缩放到两倍大小。

```tl title="Script/Scene.tl"
local world = Platformer.PlatformWorld()
world.camera.boundary = Rect(-1250, -500, 2500, 1000)
world.camera.followRatio = Vec2(0.02, 0.02)
world.camera.zoom = View.size.width / DesignWidth
world:gslot("AppSizeChanged", function()
	world.camera.zoom = View.size.width / DesignWidth
end)
```

&emsp;&emsp;接下来，我们创建了一个[BodyDef](/docs/api/Class/BodyDef)对象，这个对象用来描述游戏场景物理对象的定义。我们附加了四个多边形，这些多边形将作为游戏场景边界碰撞的物理对象：

```tl title="Script/Scene.tl"
local terrainDef = BodyDef()
terrainDef.type = "Static"
terrainDef:attachPolygon(Vec2(0, -500), 2500, 10, 0, 1, 1, 0)
terrainDef:attachPolygon(Vec2(0, 500), 2500, 10, 0, 1, 1, 0)
terrainDef:attachPolygon(Vec2(1250, 0), 10, 1000, 0, 1, 1, 0)
terrainDef:attachPolygon(Vec2(-1250, 0), 10, 1000, 0, 1, 1, 0)
```

&emsp;&emsp;然后，我们创建了一个[Body](/docs/api/Class/Body)对象，这是由terrainDef定义对象创建的物理实体，也是一个场景节点的类型，可以挂在到游戏场景中。我们设置了它的顺序和组，然后添加了四个Rectangle对象作为场景的可视图形对象。这些Rectangle对象是用于展示物理场景的图形节点：

```tl title="Script/Scene.tl"
local terrain = Body(terrainDef, world, Vec2.zero)
terrain.order = Config.TerrainLayer
terrain.group = Config.TerrainGroup
terrain:addChild(Rectangle{
	y = -500,
	width = 2500,
	height = 10,
	fillColor = fillColor,
	borderColor = borderColor,
	fillOrder = 1,
	lineOrder = 2
})
terrain:addChild(Rectangle{
	x = 1250,
	y = 0,
	width = 10,
	height = 1000,
	fillColor = fillColor,
	borderColor = borderColor,
	fillOrder = 1,
	lineOrder = 2
})
terrain:addChild(Rectangle{
	x = -1250,
	y = 0,
	width = 10,
	height = 1000,
	fillColor = fillColor,
	borderColor = borderColor,
	fillOrder = 1,
	lineOrder = 2
})
```

接着，我们将terrain对象添加到world对象中，然后将world对象添加到[Director.entry](/docs/api/Class/Director#entry)中。这里的Director.entry是引擎提供的创建游戏场景树的根节点接口：

```tl title="Script/Scene.tl"
world:addChild(terrain)
Director.entry:addChild(world)
```

然后，我们将world对象保存在[Platformer.Data.store](/docs/api/Class/Platformer/Data#store)中，这样其他模块就可以访问这个对象了：

```tl title="Script/Scene.tl"
Platformer.Data.store["Scene:world"] = world
```

最后，我们创建了一个[Entity](/docs/api/Class/Entity)对象，并调用了`Loader.loadExcel()`函数。这两行代码的具体作用将在后续的教程中进行解释：

```tl title="Script/Scene.tl"
Entity{player = true}
Loader.loadExcel()
```

至此，我们的场景创建模块就编写完成了。在接下来的教程中，我们将使用这个场景来创建游戏角色和实现游戏逻辑。希望你能跟上我们的步伐，一起学习Dora SSR游戏引擎的使用方法！